package com.rose.springbootgeneratefile.config;

import com.rose.springbootgeneratefile.api.*;
import com.rose.springbootgeneratefile.internal.ObjectFactory;
import com.rose.springbootgeneratefile.internal.db.DatabaseIntrospector;
import com.rose.springbootgeneratefile.utils.StringUtility;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static ch.qos.logback.core.db.DBHelper.closeConnection;

public class Context extends PropertyHolder{

    public Context() {
        super();
        tableConfigurations = new ArrayList<TableConfiguration>();
    }
    private String id;
    /**
     * 数据库连接属性
     */
    private JDBCConnectionConfiguration jdbcConnectionConfiguration;
    /**
     * 数据库相关配置信息，table标签中的内容
     */
    private ArrayList<TableConfiguration> tableConfigurations;
    /**
     * 所有需要建模的表
     */
    private List<IntrospectedTable> introspectedTables;
    /**
     * 数据库表列对象的实现类型
     */
    private String introspectedColumnImpl;
    /**
     * 运行时环境
     */
    private String targetRuntime;
    /**
     * 生成注释的实现类
     */
    private CommentGenerator commentGenerator;
    /**
     * java代码格式化对象
     */
    private JavaFormatter javaFormatter;
    /**
     *  生成model模型配置
     */
    private JavaModelGeneratorConfiguration javaModelGeneratorConfiguration;
    /**
     * java类型解析器配置
     */
    private JavaTypeResolverConfiguration javaTypeResolverConfiguration;
    public void setJavaTypeResolverConfiguration(
            JavaTypeResolverConfiguration javaTypeResolverConfiguration) {
        this.javaTypeResolverConfiguration = javaTypeResolverConfiguration;
    }
    public JavaTypeResolverConfiguration getJavaTypeResolverConfiguration() {
        return javaTypeResolverConfiguration;
    }
    public JavaModelGeneratorConfiguration getJavaModelGeneratorConfiguration() {
        return javaModelGeneratorConfiguration;
    }

    public void setJavaModelGeneratorConfiguration(
            JavaModelGeneratorConfiguration javaModelGeneratorConfiguration) {
        this.javaModelGeneratorConfiguration = javaModelGeneratorConfiguration;
    }

    public void setCommentGenerator(CommentGenerator commentGenerator) {
        this.commentGenerator = commentGenerator;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public JDBCConnectionConfiguration getJdbcConnectionConfiguration() {
        return jdbcConnectionConfiguration;
    }

    public void setJdbcConnectionConfiguration(JDBCConnectionConfiguration jdbcConnectionConfiguration) {
        this.jdbcConnectionConfiguration = jdbcConnectionConfiguration;
    }

    public ArrayList<TableConfiguration> getTableConfigurations() {
        return tableConfigurations;
    }

    public void addTableConfiguration(TableConfiguration tc) {
        tableConfigurations.add(tc);
    }

    public List<IntrospectedTable> getIntrospectedTables() {
        return introspectedTables;
    }

    public void setIntrospectedTables(List<IntrospectedTable> introspectedTables) {
        this.introspectedTables = introspectedTables;
    }

    public String getTargetRuntime() {
        return targetRuntime;
    }

    public void setTargetRuntime(String targetRuntime) {
        this.targetRuntime = targetRuntime;
    }

    public String getIntrospectedColumnImpl() {
        return introspectedColumnImpl;
    }

    public void setIntrospectedColumnImpl(String introspectedColumnImpl) {
        this.introspectedColumnImpl = introspectedColumnImpl;
    }

    /**
     * 初始数据库内容到对应类中
     * @param fullyQualifiedTableNames
     * @throws SQLException
     * @throws InterruptedException
     */
    public void introspectTables(Set<String> fullyQualifiedTableNames) throws SQLException, InterruptedException {

        introspectedTables = new ArrayList<IntrospectedTable>();
        JavaTypeResolver javaTypeResolver = ObjectFactory
                .createJavaTypeResolver(this);

        Connection connection = null;

        try {
            connection = getConnection();

            DatabaseIntrospector databaseIntrospector = new DatabaseIntrospector(this, connection.getMetaData(),javaTypeResolver);

            for (TableConfiguration tc : tableConfigurations) {
                String tableName = StringUtility.composeFullyQualifiedTableName(tc.getCatalog(),
                        tc.getSchema(), tc.getTableName(), '.');

                List<IntrospectedTable> tables = databaseIntrospector
                        .introspectTables(tc);

                if (tables != null) {
                    introspectedTables.addAll(tables);
                }

            }
        } finally {
            closeConnection(connection);
        }
    }

    /**
     * 获取数据库连接
     * @return
     * @throws SQLException
     */
    private Connection getConnection() throws SQLException {
        ConnectionFactory connectionFactory;
        if (jdbcConnectionConfiguration != null) {
            connectionFactory = new JDBCConnectionFactory(jdbcConnectionConfiguration);
        } else {
            throw new RuntimeException("未找到数据库配置，请检查！"); //$NON-NLS-1$
        }

        return connectionFactory.getConnection();
    }

    /**
     * 生成文件基础类型接口
     * @param generatedJavaFiles
     * @param generatedXmlFiles
     */
    public void generateFiles(List<GeneratedJavaFile> generatedJavaFiles, List<GeneratedXmlFile> generatedXmlFiles) {
        if (introspectedTables != null) {

            for (IntrospectedTable introspectedTable : introspectedTables) {
                introspectedTable.initialize();
                introspectedTable.calculateGenerators();
                generatedJavaFiles.addAll(introspectedTable.getGeneratedJavaFiles());
//                generatedXmlFiles.addAll(introspectedTable.getGeneratedXmlFiles());

            }
        }

    }

    /**
     * 获取注释生成实现类对象
     * @return
     */
    public CommentGenerator getCommentGenerator() {
        if (commentGenerator == null) {
            commentGenerator = ObjectFactory.createCommentGenerator(this);
        }

        return commentGenerator;
    }

    public JavaFormatter getJavaFormatter() {
        if (javaFormatter == null) {
            javaFormatter = ObjectFactory.createJavaFormatter(this);
        }

        return javaFormatter;
    }
}
